#pragma once


inline void packDatetime5(uint16_t y, uint8_t mo, uint8_t d,
                          uint8_t h, uint8_t mi, uint8_t s,
                          uint8_t out[5]) {
    uint64_t v = 0;
    v = (v << 14) | y;
    v = (v << 4)  | mo;
    v = (v << 5)  | d;
    v = (v << 5)  | h;
    v = (v << 6)  | mi;
    v = (v << 6)  | s;
    out[0] = static_cast<uint8_t>((v >> 32) & 0xFF);
    out[1] = static_cast<uint8_t>((v >> 24) & 0xFF);
    out[2] = static_cast<uint8_t>((v >> 16) & 0xFF);
    out[3] = static_cast<uint8_t>((v >> 8)  & 0xFF);
    out[4] = static_cast<uint8_t>(v & 0xFF);
}
// out5 会自动退化为 *out5
inline bool parseDatetimeStringTo5(const char* ts19, uint8_t out5[5]) {
    // 期望格式: "YYYY-MM-DD HH:MM:SS"
    uint16_t y = (ts19[0]-'0')*1000 + (ts19[1]-'0')*100 + (ts19[2]-'0')*10 + (ts19[3]-'0');
    uint8_t  mo = (ts19[5]-'0')*10 + (ts19[6]-'0');
    uint8_t  d  = (ts19[8]-'0')*10 + (ts19[9]-'0');
    uint8_t  h  = (ts19[11]-'0')*10 + (ts19[12]-'0');
    uint8_t  mi = (ts19[14]-'0')*10 + (ts19[15]-'0');
    uint8_t  s  = (ts19[17]-'0')*10 + (ts19[18]-'0');
    if (y>9999 || mo<1 || mo>12 || d<1 || d>31 || h>23 || mi>59 || s>59) return false;
    packDatetime5(y, mo, d, h, mi, s, out5);
    return true;
}


// 解包 5 字节 → y/mo/d/h/mi/s
inline void unpackDatetime5(const uint8_t in[5],
                            uint16_t &y, uint8_t &mo, uint8_t &d,
                            uint8_t &h, uint8_t &mi, uint8_t &s) {
    uint64_t v = (static_cast<uint64_t>(in[0])<<32) |
                 (static_cast<uint64_t>(in[1])<<24) |
                 (static_cast<uint64_t>(in[2])<<16) |
                 (static_cast<uint64_t>(in[3])<<8)  |
                 (static_cast<uint64_t>(in[4]));
    s  = static_cast<uint8_t>(v & 0x3F); v >>= 6;
    mi = static_cast<uint8_t>(v & 0x3F); v >>= 6;
    h  = static_cast<uint8_t>(v & 0x1F); v >>= 5;
    d  = static_cast<uint8_t>(v & 0x1F); v >>= 5;
    mo = static_cast<uint8_t>(v & 0x0F); v >>= 4;
    y  = static_cast<uint16_t>(v & 0x3FFF);
}
inline std::string formatDatetime5(const uint8_t in5[5]) {
    uint16_t y; uint8_t mo,d,h,mi,s;
    unpackDatetime5(in5, y, mo, d, h, mi, s);
    char buf[20];
    std::snprintf(buf, sizeof(buf), "%04u-%02u-%02u %02u:%02u:%02u",
                  static_cast<unsigned>(y),
                  static_cast<unsigned>(mo),
                  static_cast<unsigned>(d),
                  static_cast<unsigned>(h),
                  static_cast<unsigned>(mi),
                  static_cast<unsigned>(s));
    return std::string(buf);
}

inline uint64_t nowMs() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now().time_since_epoch()
    ).count();
}